package cn.itsource.ymcc.service.impl;

import cn.itsource.ymcc.constant.KillConstants;
import cn.itsource.ymcc.constant.OrderStatusConstants;
import cn.itsource.ymcc.constant.RConst;
import cn.itsource.ymcc.domain.CourseDoc;
import cn.itsource.ymcc.domain.CourseOrder;
import cn.itsource.ymcc.domain.CourseOrderItem;
import cn.itsource.ymcc.dto.PayOrderDto;
import cn.itsource.ymcc.dto.PreOrderDto;
import cn.itsource.ymcc.mapper.CourseOrderItemMapper;
import cn.itsource.ymcc.mapper.CourseOrderMapper;
import cn.itsource.ymcc.openfeign.SearchCourseOpenfeign;
import cn.itsource.ymcc.producer.OrderMessageProducer;
import cn.itsource.ymcc.result.JsonResult;
import cn.itsource.ymcc.service.ICourseOrderService;
import cn.itsource.ymcc.util.AssertUtil;
import cn.itsource.ymcc.util.CodeGenerateUtils;
import cn.itsource.ymcc.vo.KillOrderFormVo;
import cn.itsource.ymcc.vo.OrderFormVo;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zongchangjiang
 * @since 2023-07-06
 */
@Service
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {

    @Autowired
    private SearchCourseOpenfeign searchCourseOpenfeign;
    @Autowired
    private CourseOrderItemMapper courseOrderItemMapper;
    @Autowired
    private OrderMessageProducer orderMessageProducer;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 下单的业务逻辑实现
     * @param orderFormVo
     * @param userId
     * @return
     */
    @Override
    public JsonResult placeOrder(OrderFormVo orderFormVo, Long userId) {
        AssertUtil.isTrue(redisTemplate.hasKey(orderFormVo.getToken()),"请勿重复提交");
        //找到订单数据
        JsonResult jsonResult = searchCourseOpenfeign.queryCourseDocByIds(orderFormVo.getCourseIds());
        List<CourseDoc> courseDocs = JSON.parseArray(jsonResult.getData().toString(), CourseDoc.class);
        //保存订单数据
        CourseOrder courseOrder = saveOrderInfo(courseDocs,orderFormVo,userId);
        //保存订单明细
        List<CourseOrderItem> list = saveOrderItemInfo(courseOrder, courseDocs);
        courseOrder.setList(list);


        /*
         * String txProducerGroup, 组名
         * String destination,  主题
         * Message<?> message, 消费者需要的数据  需要生成pay支付单的数据
         * Object arg        本地事务要执行的东西
         */
        PayOrderDto payOrderDto = builderPayOrderDto(orderFormVo.getCourseIds().get(0), courseOrder);
        commonSendMSG(courseOrder, payOrderDto);

        //删除token
        redisTemplate.delete(orderFormVo.getToken());
        return JsonResult.success().setData(courseOrder.getOrderNo());
    }

    private void commonSendMSG(CourseOrder courseOrder, PayOrderDto payOrderDto) {
        //发送一个事务消息
        TransactionSendResult transactionSendResult = rocketMQTemplate.sendMessageInTransaction(OrderStatusConstants.MQ_COURSEORDER_PAY_GROUP_TRANSACTION,
                OrderStatusConstants.MQ_TOPIC_COURSE_ORDER_PUSH_TO_TRANSACTION + ":" + OrderStatusConstants.MQ_TAGS_COURSE_ORDER_PUSH_TO_TRANSACTION,
                MessageBuilder.withPayload(JSON.toJSONString(payOrderDto)).build(),
                courseOrder);
        AssertUtil.isTrue(transactionSendResult.getLocalTransactionState() != LocalTransactionState.ROLLBACK_MESSAGE,"保存订单信息失败");


        //发送通知
        orderMessageProducer.syncSend(courseOrder);
        orderMessageProducer.syncSendDelay(courseOrder);
        orderMessageProducer.syncSendDelayCloseOrder(courseOrder.getOrderNo());
    }

    /**
     * 秒杀下单的逻辑
     * @param killOrderFormVo
     * @param userId
     * @return
     */
    @Override
    public JsonResult killPlaceOrder(KillOrderFormVo killOrderFormVo, Long userId) {
        AssertUtil.isTrue(redisTemplate.hasKey(killOrderFormVo.getToken()),"请勿重复提交");

        PreOrderDto preOrderDto = (PreOrderDto)redisTemplate.opsForValue().get(KillConstants.KEY_PREFIX_PRE_ORDER + killOrderFormVo.getOrderNo());
        //秒杀保存订单数据
        CourseOrder courseOrder = saveKillOrderInfo(preOrderDto,killOrderFormVo,userId);
        //秒杀保存订单明细
        List<CourseOrderItem> list = saveOrderItemInfo(courseOrder, preOrderDto);
        courseOrder.setList(list);
        //生成支付单数据
        PayOrderDto payOrderDto = builderPayOrderDto(preOrderDto.getCourseId(), courseOrder);
        commonSendMSG(courseOrder, payOrderDto);

        //删除token
        redisTemplate.delete(killOrderFormVo.getToken());
        return JsonResult.success().setData(killOrderFormVo.getOrderNo());
    }


    private PayOrderDto builderPayOrderDto(Long courseId, CourseOrder courseOrder) {
        PayOrderDto payOrderDto = new PayOrderDto();
        payOrderDto.setCreateTime(new Date());
        payOrderDto.setAmount(courseOrder.getPayAmount());
        payOrderDto.setOrderNo(courseOrder.getOrderNo());
        payOrderDto.setPayStatus(courseOrder.getStatusOrder());
        payOrderDto.setPayType(courseOrder.getPayType());
        payOrderDto.setUserId(courseOrder.getUserId());
        payOrderDto.setSubject(courseOrder.getTitle());
        payOrderDto.setRelationId(courseId);
        return payOrderDto;
    }

    @Transactional
    @Override
    public void saveTransactionCourseOrder(CourseOrder o) {
        baseMapper.insert(o);
        o.getList().stream().map(courseOrderItem -> {
            courseOrderItem.setOrderId(o.getId());
            return courseOrderItem;
        }).forEach(courseOrderItemMapper::insert);
    }



    /**
     * 保存订单明细
     * @param courseOrder
     * @return
     */
    private List<CourseOrderItem> saveOrderItemInfo(CourseOrder courseOrder,List<CourseDoc> courseDocs) {
        List<CourseOrderItem> list = new ArrayList<>();
        for (CourseDoc courseDoc : courseDocs) {
            CourseOrderItem courseOrderItem = new CourseOrderItem();
            //        对应订单ID
            courseOrderItem.setOrderId(courseOrder.getId());
//        小计金额
            courseOrderItem.setAmount(new BigDecimal(courseDoc.getPrice()));
//        课程价格
            courseOrderItem.setPrice(new BigDecimal(courseDoc.getPrice()));
//        课程的数量
            courseOrderItem.setCount(RConst.Num.INT_1);
//        课程ID
            courseOrderItem.setCourseId(courseDoc.getId());
//        课程名字
            courseOrderItem.setCourseName(courseDoc.getName());
//        封面
            courseOrderItem.setCoursePic(courseDoc.getPic());
            //订单号
            courseOrderItem.setOrderNo(courseOrder.getOrderNo());
            list.add(courseOrderItem);
        }
        return list;
    }

    /**
     * 保存订单信息
     * @param courseDocs
     * @param orderFormVo
     * @param userId
     * @return
     */
    private CourseOrder saveOrderInfo(List<CourseDoc> courseDocs, OrderFormVo orderFormVo, Long userId) {
        CourseOrder courseOrder = new CourseOrder();
//        创建时间
        courseOrder.setCreateTime(new Date());
//        订单编号
        courseOrder.setOrderNo(CodeGenerateUtils.generateOrderSn(userId));
//         支付总的原价格
        BigDecimal totalAmount = courseDocs.stream()
                .map(doc -> new BigDecimal(doc.getPriceOld()))
                .reduce(BigDecimal.ZERO, (a, b) -> (a.add(b)));
        courseOrder.setTotalAmount(totalAmount);
//        支付金额
        BigDecimal price = courseDocs.stream()
                .map(doc -> new BigDecimal(doc.getPrice()))
                .reduce(BigDecimal.ZERO, (a, b) -> (a.add(b)));
        courseOrder.setPayAmount(price);
//         优惠金额
        courseOrder.setDiscountAmount(totalAmount.subtract(price));
//        数量
        courseOrder.setTotalCount(courseDocs.size());
//        用户id
        courseOrder.setUserId(userId);
//        支付方式:0余额直接，1支付宝，2微信,3银联
        courseOrder.setPayType(orderFormVo.getPayType());

//        订单状态：0下单成功待支付，1已支付，2订单取消，3订单退款，4支付超时或失败，5订单确认订单完成
        courseOrder.setStatusOrder(OrderStatusConstants.ORDER_DEFAULT);
//        0普通订单 ， 1秒杀订单
        courseOrder.setOrderType(OrderStatusConstants.ORDER_TYPE_DEFAULT);
        //        订单标题
        courseOrder.setTitle(OrderStatusConstants.ORDER_TYPE_DEFAULT_NAME);
        return courseOrder;
    }

    /**
     * 保存订单信息
     * @param preOrderDto
     * @param killOrderFormVo
     * @param userId
     * @return
     */
    private CourseOrder saveKillOrderInfo(PreOrderDto preOrderDto, KillOrderFormVo killOrderFormVo, Long userId) {
        CourseOrder courseOrder = new CourseOrder();
//        创建时间
        courseOrder.setCreateTime(new Date());
//        订单编号
        courseOrder.setOrderNo(preOrderDto.getOrderNo());//------------------------------
//         支付总的原价格
        courseOrder.setTotalAmount(preOrderDto.getPrice());
//        支付金额
        courseOrder.setPayAmount(preOrderDto.getPrice());
//         优惠金额
        courseOrder.setDiscountAmount(new BigDecimal(0.0));
//        数量
        courseOrder.setTotalCount(preOrderDto.getCount());
//        用户id
        courseOrder.setUserId(userId);
//        支付方式:0余额直接，1支付宝，2微信,3银联
        courseOrder.setPayType(killOrderFormVo.getPayType());
//        订单状态：0下单成功待支付，1已支付，2订单取消，3订单退款，4支付超时或失败，5订单确认订单完成
        courseOrder.setStatusOrder(OrderStatusConstants.ORDER_DEFAULT);
//        0普通订单 ， 1秒杀订单
        courseOrder.setOrderType(OrderStatusConstants.ORDER_TYPE_KILL);
        //        订单标题
        courseOrder.setTitle(preOrderDto.getTitle());
        return courseOrder;
    }


    /**
     * 保存订单明细
     * @param courseOrder
     * @return
     */
    private List<CourseOrderItem> saveOrderItemInfo(CourseOrder courseOrder,PreOrderDto preOrderDto) {
        List<CourseOrderItem> list = new ArrayList<>();

            CourseOrderItem courseOrderItem = new CourseOrderItem();
            //        对应订单ID
            courseOrderItem.setOrderId(courseOrder.getId());
//        小计金额
            courseOrderItem.setAmount(preOrderDto.getPrice());
//        课程价格
            courseOrderItem.setPrice(preOrderDto.getPrice());
//        课程的数量
            courseOrderItem.setCount(preOrderDto.getCount());
//        课程ID
            courseOrderItem.setCourseId(preOrderDto.getCourseId());
//        课程名字
            courseOrderItem.setCourseName(preOrderDto.getCourseName());
//        封面
            courseOrderItem.setCoursePic(preOrderDto.getCoursePic());
            //订单号
            courseOrderItem.setOrderNo(courseOrder.getOrderNo());
            list.add(courseOrderItem);
        return list;
    }


}
